/* SexpMethodCallMessage.cs -- 
   Copyright (C) 2008  Casey Marshall.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.  */


using System;
using System.Reflection;
using System.Runtime.Remoting.Messaging;

namespace SexpSharp.Remoting
{
    public class SexpMethodCallMessage : IMethodCallMessage
    {
        private MethodBase methodBase;
        private object[] args;
        private object[] inArgs;
        private string typeName;
        private string uri;

        public SexpMethodCallMessage(MethodBase methodBase, string typeName,
                                     object[] args, string uri)
        {
            this.methodBase = methodBase;
            this.typeName = typeName;
            this.args = args;
            int inargCount = 0;
            ParameterInfo[] param = methodBase.GetParameters();
            foreach (ParameterInfo p in param)
                if (p.IsIn || !(p.IsOut || p.ParameterType.IsByRef))
                    inargCount++;
            inArgs = new object[inargCount];
            for (int i = 0, j = 0; i < param.Length; i++)
            {
                if (param[i].IsIn
                    || !(param[i].IsOut || param[i].ParameterType.IsByRef))
                    inArgs[j++] = args[i];
            }
            this.uri = uri;
        }

#region IMethodCallMessage
        public object GetInArg(int arg_num)
        {
            return inArgs[arg_num];
        }

        public string GetInArgName(int arg_num)
        {
            ParameterInfo[] param = methodBase.GetParameters();
            foreach (ParameterInfo p in param)
                if (p.IsIn || !(p.IsOut || p.ParameterType.IsByRef))
                    if (arg_num-- == 0)
                        return p.Name;
            throw new ArgumentException("no in arg: " + arg_num);
        }

        public int InArgCount
        {
            get {
                return inArgs.Length;
            }
        }

        public object[] InArgs
        {
            get {
                return inArgs;
            }
        }
#endregion

#region IMethodMessage

        public object GetArg(int arg_num)
        {
            return args[arg_num];
        }

        public string GetArgName(int arg_num)
        {
            return methodBase.GetParameters()[arg_num].Name;
        }

        public int ArgCount {
            get {
                return args.Length;
            }
        }

        public object[] Args {
            get {
                return args;
            }
        }

        public bool HasVarArgs {
            get {
                return false; // XXX ?
            }
        }

        public LogicalCallContext LogicalCallContext {
            get {
                return null; // XXX ?
            }
        }

        public MethodBase MethodBase {
            get {
                return methodBase;
            }
        }

        public string MethodName {
            get {
                return methodBase.Name;
            }
        }

        public object MethodSignature {
            get {
                ParameterInfo[] param = methodBase.GetParameters();
                Type[] sig = new Type[param.Length];
                for (int i = 0; i < param.Length; i++)
                    sig[i] = param[i].ParameterType;
                return sig;
            }
        }

        public string TypeName {
            get {
                return typeName;
            }
        }

        public string Uri {
            get {
                return uri;
            }
        }
#endregion

#region IMessage

        public System.Collections.IDictionary Properties {
            get {
                return null;
            }
        }

#endregion
    }
}